using System;

namespace Com.SimonProctor.Html
{
	/// <summary>
	/// Enumeration for indicating the type of parse event encountered.
	/// </summary>
	public enum ParseType
	{
		/// <summary>
		/// A start tag
		/// </summary>
		Start, 
		/// <summary>
		/// An end tag
		/// </summary>
		End, 
		/// <summary>
		/// A comment
		/// </summary>
		Comment, 
		/// <summary>
		/// A declaration
		/// </summary>
		Declaration, 
		/// <summary>
		/// Text
		/// </summary>
		Text
	};

    /// <summary>
    /// Base parsing event. Wraps the type of event and the text
    /// involved. Sub classes may also add additional parameters.
    /// </summary>
    public class ParseEvent
    {
        private ParseType type;
        private string text;

        /// <summary>
        /// Sets up the type and text for this event
        /// </summary>
        /// <param name="type">The type of parse event</param>
        /// <param name="text">The associated text</param>
        public ParseEvent(ParseType type, string text)
        {
            this.type = type;
            this.text = text;
        }

        /// <summary>
        /// The text relating to this event.
        /// </summary>
        public string Text
        {
            get
            {
                return this.text;
            }
        }

        /// <summary>
        /// The type of event. This may not be necessary as we have
        /// subclassed this event so we can inspect by type rather than
        /// field query. More tests needed to discover best way!
        /// </summary>
        public ParseType Type
        {
            get
            {
                return this.type;
            }
        }
    }

    /// <summary>
    /// Used by the event code from the parser. Passes the event details
    /// out to the subscribing classes. 
    /// </summary>
    public class ParseEventArgs : System.EventArgs
    {
        private ParseEvent htmlEvent;

        /// <summary>
        /// Sets up our event with the HTML event we are handling and 
        /// wraps it in a way to allow events to fire.
        /// </summary>
        /// <param name="htmlEvent">The HTML event that has fired</param>
        public ParseEventArgs(ParseEvent htmlEvent)
        {
            this.htmlEvent = htmlEvent;
        }

        /// <summary>
        /// Returns the HTML event associated with this stage of the
        /// parse run.
        /// </summary>
        public ParseEvent HtmlEvent
        {
            get
            {
                return this.htmlEvent;
            }
        }
    }

	/// <summary>
	/// Event args for a comment found in the markup
	/// </summary>
	// public delegate void CommentEventHandler(object sender, EventArgs e);
    public class CommentEventArgs : ParseEventArgs
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="htmlEvent"></param>
        public CommentEventArgs(CommentEvent htmlEvent) : base(htmlEvent)
        {
        }
    }

	/// <summary>
    /// Event args for a start tag found in the markup.
	/// </summary>
	//public delegate void StartTagEventHandler(object sender, EventArgs e);
    public class StartTagEventArgs : ParseEventArgs
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="htmlEvent"></param>
        public StartTagEventArgs(StartEvent htmlEvent) : base(htmlEvent)
        {
        }
    }

	/// <summary>
    /// Event args for an end tag found in the markup.
	/// </summary>
	// public delegate void EndTagEventHandler(object sender, EventArgs e);
    public class EndTagEventArgs : ParseEventArgs
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="htmlEvent"></param>
        public EndTagEventArgs(EndEvent htmlEvent) : base(htmlEvent)
        {
        }
    }

	/// <summary>
    /// Event args for a block of text found in the markup.
	/// </summary>
	// public delegate void TextEventHandler(object sender, EventArgs e);
    public class TextEventArgs : ParseEventArgs
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="htmlEvent"></param>
        public TextEventArgs(TextEvent htmlEvent) : base(htmlEvent)
        {
        }
    }

	/// <summary>
    /// Event args for a declaration found in the markup.
	/// </summary>
	// public delegate void DeclarationEventHandler(object sender, EventArgs e);
    public class DeclarationEventArgs : ParseEventArgs
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="htmlEvent"></param>
        public DeclarationEventArgs(DeclarationEvent htmlEvent) : base(htmlEvent)
        {
        }
    }

	/// <summary>
	/// Parse event for a start tag. Also provides attributes from this
	/// start tag as a hashtable
	/// </summary>
	public class StartEvent : ParseEvent
	{
		System.Collections.Hashtable attr;

		/// <summary>
		/// Setup the base class type and text. Save the attributes here.
		/// </summary>
		/// <param name="text">The tagname</param>
		/// <param name="attr">The attributes</param>
		public StartEvent(string text, System.Collections.Hashtable attr) : base(ParseType.Start, text)
		{
			this.attr = attr;
		}

		/// <summary>
		/// The attributes from this start tag
		/// </summary>
		public virtual System.Collections.Hashtable Attributes
		{
			get
			{
				return attr;
			}
		}
	}

	/// <summary>
	/// Parse event for an end tag. 
	/// </summary>
	public class EndEvent : ParseEvent 
	{
		/// <summary>
		/// Setup the base class type and text.
		/// </summary>
		/// <param name="text">The end tag name</param>
		public EndEvent(string text) : base(ParseType.End, text)
		{
		}
	}
	
	/// <summary>
	/// Parse event for text
	/// </summary>
	public class TextEvent : ParseEvent
	{
		/// <summary>
		/// Setup the base class type and text.
		/// </summary>
		/// <param name="text">The whole text</param>
		public TextEvent(string text) : base(ParseType.Text, text)
		{
		}
	}

	/// <summary>
	/// Parse event for a comment. 
	/// </summary>
	public class CommentEvent : ParseEvent
	{
		/// <summary>
		/// Setup the base class type and text.
		/// </summary>
		/// <param name="text">The comment (with the -- intact)</param>
		public CommentEvent(string text) : base(ParseType.Comment, text)
		{
		}
	}

	/// <summary>
	/// Parse event for a declaration.
	/// </summary>
	public class DeclarationEvent : ParseEvent
	{
		/// <summary>
		/// Setup the base class type and text.
		/// </summary>
		/// <param name="text">The declaration</param>
		public DeclarationEvent(string text) : base(ParseType.Declaration, text)
		{
		}
	}
}
